package com.fulihui.information.service;

import com.fulihui.information.api.ContentService;
import com.fulihui.information.biz.content.ContentBizManager;
import com.fulihui.information.biz.content.FullDateManager;
import com.fulihui.information.biz.content.ObtainAppListPageHandler;
import com.fulihui.information.biz.content.impl.handler.AppListPageObtainHandlerRegister;
import com.fulihui.information.biz.counter.ContentCommentTimesOperableCounter;
import com.fulihui.information.common.ESortType;
import com.fulihui.information.common.config.AppConst;
import com.fulihui.information.core.db.ContentListItemDB;
import com.fulihui.information.core.db.ContentTopDB;
import com.fulihui.information.core.repository.ContentRepository;
import com.fulihui.information.dto.ContentDTO;
import com.fulihui.information.dto.ContentListItemDTO;
import com.fulihui.information.enums.EContentSortFields;
import com.fulihui.information.enums.EContentStatus;
import com.fulihui.information.enums.EDataObtainType;
import com.fulihui.information.enums.EYesOrNo;
import com.fulihui.information.request.*;
import org.near.servicesupport.error.Errors;
import org.near.servicesupport.error.InvokeServiceException;
import org.near.servicesupport.result.BaseResult;
import org.near.servicesupport.result.ResultBuilder;
import org.near.servicesupport.result.TPageResult;
import org.near.servicesupport.result.TSingleResult;
import org.near.servicesupport.util.ServiceAssert;
import org.near.toolkit.common.EnumUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import static org.near.servicesupport.result.ResultBuilder.*;
import static org.near.toolkit.common.EnumUtil.queryByCode;
import static org.springframework.util.CollectionUtils.isEmpty;

/**
 * @author Willard.Hu on 2016/12/26 0026.
 */
@Service("contentService")
public class ContentServiceImpl implements ContentService {
    @Autowired
    private ContentRepository                contentRepository;
    @Autowired
    private FullDateManager                    fullDateManager;
    @Autowired
    @Qualifier("redisContentListItemDB")
    private ContentListItemDB                  contentListItemDB;
    @Autowired
    @Qualifier("redisContentTopDB")
    private ContentTopDB                       contentTopDB;
    @Autowired
    private AppListPageObtainHandlerRegister   appListPageObtainHandlerRegister;
    @Autowired
    private ContentBizManager                  contentBizManager;
    @Autowired
    private ContentCommentTimesOperableCounter contentCommentTimesOperableCounter;

    /**
     * @see ContentService#batchModifyStatus(ContentBatchModifyStatusRequest)
     */
    @Override
    public BaseResult batchModifyStatus(ContentBatchModifyStatusRequest request) {
        String status = request.getStatus();
        Assert.isTrue(EnumUtil.inEnum(status, EContentStatus.class));

        List<ContentListItemDTO> items = contentRepository.queryItemListByIds(
                new ArrayList<>(request.getContentIds()));
        // 请求参数获取不到任何资讯信息识别为参数有问题
        if (isEmpty(items)) {
            return fail(Errors.Commons.REQUEST_PARAMETER_ERROR);
        }

        if (EContentStatus.CHECK.getCode().equals(status)) {
            // 将审批的内容同步到Redis数据库
            contentBizManager.saveItemsToRedis(items);
        } else if (EContentStatus.DELETE.getCode().equals(status)
                || EContentStatus.UNCHECK.getCode().equals(status)) {
            // 将下架或者删除的内容从Redis数据库中移除
            contentBizManager.removeItemsToRedis(items);

            // 置顶资讯在下架或删除内容中，将Redis的置顶数据页移出，数据库置顶状态的修改由
            // contentRepository.batchModifyStatus 方法中处理
            // XXX 目前只有热门置顶，所有类目都支持置顶需要修改此处逻辑
            ContentListItemDTO top = contentTopDB.getTop(AppConst.CONTENT_HOTS_CATEGORY_CODE);
            if (top != null && request.getContentIds().contains(top.getId())) {
                contentTopDB.remove(AppConst.CONTENT_HOTS_CATEGORY_CODE);
            }
        }

        boolean rs = contentRepository.batchModifyStatus(request.getContentIds(),
                request.getStatus(), request.getOperator());
        return rs ? succ() : fail(Errors.Commons.SYSTEM_ERROR);
    }

    /**
     * @see ContentService#top(ContentTopRequest)
     */
    @Override
    public BaseResult top(ContentTopRequest request) {
        ContentDTO detail = contentRepository.detail(request.getContentId());
        ContentListItemDTO item = new ContentListItemDTO();
        BeanUtils.copyProperties(detail, item);
        item.setTopStatus(EYesOrNo.YES.getCode());
        // 设置到置顶库中
        if (AppConst.CONTENT_ESSAY_JOKE_CATEGORY_CODE.equals(item.getCategoryCode())) {
            // 段子赞不支持置顶
            throw new InvokeServiceException(Errors.Commons.REQUEST_PARAMETER_ERROR);
        } else {
            // XXX 存缓存使用热门类目，目前只有热门类目
            //contentTopDB.setTop(item.getCategoryCode(), item);
            contentTopDB.setTop(AppConst.CONTENT_HOTS_CATEGORY_CODE, item);
            contentRepository.setTop(item.getId(), item.getCategoryCode(), request.getOperator());
        }
        return succ();
    }

    @Override
    public BaseResult modifyContent(ModifyContentRequest request) {
        // TODO 修改以后实现...
        return succ();
    }

    @Override
    public TPageResult<ContentDTO> queryPage(ContentPageQueryRequest request) {
        String status = request.getStatus();
        if (isNotEmpty(status)) {
            ServiceAssert.isTrue(EnumUtil.inEnum(status, EContentStatus.class),
                    Errors.Commons.REQUEST_PARAMETER_ERROR);
        }

        String sortType = request.getSortType();
        if (isNotEmpty(sortType)) {
            ServiceAssert.isTrue(EnumUtil.inEnum(sortType, ESortType.class),
                    Errors.Commons.REQUEST_PARAMETER_ERROR);
        }

        String sortField = request.getSortFiled();
        if (isNotEmpty(sortField)) {
            ServiceAssert.isTrue(EnumUtil.inEnum(sortField, EContentSortFields.class),
                    Errors.Commons.REQUEST_PARAMETER_ERROR);
        }

        List<ContentDTO> contentDTOList = contentRepository.queryPage(request);
        fullDateManager.fullMulti(contentDTOList);
        int queryPageCount = contentRepository.queryPageCount(request);
        return succTPage(contentDTOList, request.getPage(), request.getRows(),
                queryPageCount);
    }

    @Override
    public TSingleResult<ContentDTO> detail(ContentIdRequest request) {
        ContentDTO contentDTO = contentRepository.detail(request.getContentId());
        fullDateManager.fullSingle(contentDTO);
        return succTSingle(contentDTO);
    }

    /**
     * @see ContentService#queryPageForApp(ContentPageQueryForAppRequest)
     */
    @Override
    public TPageResult<ContentListItemDTO> queryPageForApp(ContentPageQueryForAppRequest request) {
        EDataObtainType type = queryByCode(request.getDataObtainType(), EDataObtainType.class);
        Optional<ObtainAppListPageHandler> handler = appListPageObtainHandlerRegister.get(type);
        if (!handler.isPresent()) {
            throw new InvokeServiceException(Errors.Commons.SYSTEM_ERROR);
        }
        return handler.get().execute(request);
    }

    @Override
    public TSingleResult<Long> conetntCommentTimes(ContentIdRequest request) {
        Long count = contentCommentTimesOperableCounter.count(request.getContentId());
        return succTSingle(count);
    }
}
